#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
文件批量重命名工具
支持递归遍历文件夹，对文件进行重命名、替换和删除文件名内容操作
"""

import os
import re
from pathlib import Path
from typing import List, Tuple, Optional


class FileRenamer:
    def __init__(self, root_path: str):
        """
        初始化文件重命名器
        
        Args:
            root_path: 要处理的根目录路径
        """
        self.root_path = Path(root_path)
        if not self.root_path.exists():
            raise ValueError(f"路径 {root_path} 不存在")
        if not self.root_path.is_dir():
            raise ValueError(f"路径 {root_path} 不是一个文件夹")
    
    def get_all_files(self) -> List[Path]:
        """
        递归获取所有文件（不包括文件夹）
        
        Returns:
            文件路径列表
        """
        files = []
        for file_path in self.root_path.rglob("*"):
            if file_path.is_file():
                files.append(file_path)
        return files
    
    def preview_changes(self, files: List[Path], operation: str, **kwargs) -> List[Tuple[str, str]]:
        """
        预览重命名操作
        
        Args:
            files: 文件列表
            operation: 操作类型 ('replace', 'remove', 'rename')
            **kwargs: 操作参数
            
        Returns:
            (原文件名, 新文件名) 的元组列表
        """
        changes = []
        for file_path in files:
            old_name = file_path.name
            new_name = self._generate_new_name(old_name, operation, **kwargs)
            
            if old_name != new_name:
                changes.append((str(file_path), str(file_path.parent / new_name)))
        
        return changes
    
    def _generate_new_name(self, old_name: str, operation: str, **kwargs) -> str:
        """
        根据操作类型生成新文件名
        
        Args:
            old_name: 原文件名
            operation: 操作类型
            **kwargs: 操作参数
            
        Returns:
            新文件名
        """
        if operation == 'replace':
            old_text = kwargs.get('old_text', '')
            new_text = kwargs.get('new_text', '')
            case_sensitive = kwargs.get('case_sensitive', True)
            
            if case_sensitive:
                return old_name.replace(old_text, new_text)
            else:
                # 不区分大小写的替换
                pattern = re.compile(re.escape(old_text), re.IGNORECASE)
                return pattern.sub(new_text, old_name)
        
        elif operation == 'remove':
            text_to_remove = kwargs.get('text_to_remove', '')
            case_sensitive = kwargs.get('case_sensitive', True)
            
            if case_sensitive:
                return old_name.replace(text_to_remove, '')
            else:
                # 不区分大小写的删除
                pattern = re.compile(re.escape(text_to_remove), re.IGNORECASE)
                return pattern.sub('', old_name)
        
        elif operation == 'rename':
            pattern = kwargs.get('pattern', '')
            replacement = kwargs.get('replacement', '')
            
            if pattern:
                # 支持正则表达式重命名
                return re.sub(pattern, replacement, old_name)
            else:
                return old_name
        
        return old_name
    
    def execute_rename(self, changes: List[Tuple[str, str]], dry_run: bool = True) -> List[Tuple[str, str, str]]:
        """
        执行重命名操作
        
        Args:
            changes: 要执行的更改列表
            dry_run: 是否为试运行模式
            
        Returns:
            (原路径, 新路径, 状态) 的元组列表
        """
        results = []
        
        for old_path, new_path in changes:
            old_file = Path(old_path)
            new_file = Path(new_path)
            
            try:
                if dry_run:
                    # 试运行模式，只检查是否可以重命名
                    if new_file.exists():
                        status = f"错误: 目标文件已存在 - {new_file.name}"
                    else:
                        status = "预览: 可以重命名"
                else:
                    # 实际执行重命名
                    if new_file.exists():
                        status = f"跳过: 目标文件已存在 - {new_file.name}"
                    else:
                        old_file.rename(new_file)
                        status = "成功"
                
                results.append((old_path, new_path, status))
                
            except Exception as e:
                status = f"错误: {str(e)}"
                results.append((old_path, new_path, status))
        
        return results
    
    def replace_text(self, old_text: str, new_text: str, case_sensitive: bool = True, 
                    file_filter: Optional[str] = None, dry_run: bool = True) -> List[Tuple[str, str, str]]:
        """
        替换文件名中的文本
        
        Args:
            old_text: 要替换的文本
            new_text: 替换后的文本
            case_sensitive: 是否区分大小写
            file_filter: 文件过滤模式（如 '*.txt'）
            dry_run: 是否为试运行模式
            
        Returns:
            执行结果列表
        """
        files = self.get_all_files()
        
        # 如果有文件过滤器，应用过滤
        if file_filter:
            files = [f for f in files if f.match(file_filter)]
        
        changes = self.preview_changes(files, 'replace', 
                                     old_text=old_text, new_text=new_text, 
                                     case_sensitive=case_sensitive)
        
        return self.execute_rename(changes, dry_run)
    
    def remove_text(self, text_to_remove: str, case_sensitive: bool = True, 
                   file_filter: Optional[str] = None, dry_run: bool = True) -> List[Tuple[str, str, str]]:
        """
        删除文件名中的指定文本
        
        Args:
            text_to_remove: 要删除的文本
            case_sensitive: 是否区分大小写
            file_filter: 文件过滤模式（如 '*.txt'）
            dry_run: 是否为试运行模式
            
        Returns:
            执行结果列表
        """
        files = self.get_all_files()
        
        # 如果有文件过滤器，应用过滤
        if file_filter:
            files = [f for f in files if f.match(file_filter)]
        
        changes = self.preview_changes(files, 'remove', 
                                     text_to_remove=text_to_remove, 
                                     case_sensitive=case_sensitive)
        
        return self.execute_rename(changes, dry_run)
    
    def rename_with_pattern(self, pattern: str, replacement: str, 
                           file_filter: Optional[str] = None, dry_run: bool = True) -> List[Tuple[str, str, str]]:
        """
        使用正则表达式重命名文件
        
        Args:
            pattern: 正则表达式模式
            replacement: 替换字符串
            file_filter: 文件过滤模式（如 '*.txt'）
            dry_run: 是否为试运行模式
            
        Returns:
            执行结果列表
        """
        files = self.get_all_files()
        
        # 如果有文件过滤器，应用过滤
        if file_filter:
            files = [f for f in files if f.match(file_filter)]
        
        changes = self.preview_changes(files, 'rename', 
                                     pattern=pattern, replacement=replacement)
        
        return self.execute_rename(changes, dry_run)


def print_results(results: List[Tuple[str, str, str]]):
    """打印执行结果"""
    if not results:
        print("没有文件需要重命名")
        return
    
    print(f"\n执行结果 (共 {len(results)} 个文件):")
    print("-" * 80)
    
    success_count = 0
    for old_path, new_path, status in results:
        old_name = Path(old_path).name
        new_name = Path(new_path).name
        
        if status == "成功" or status.startswith("预览"):
            success_count += 1
            print(f"✓ {old_name} -> {new_name}")
        else:
            print(f"✗ {old_name} -> {new_name} ({status})")
    
    print("-" * 80)
    print(f"成功/预览: {success_count}, 失败: {len(results) - success_count}")


def main():
    """主函数，提供命令行界面"""
    print("文件批量重命名工具")
    print("=" * 50)
    
    # 获取文件夹路径
    folder_path = input("请输入要处理的文件夹路径: ").strip()
    if not folder_path:
        print("路径不能为空")
        return
    
    try:
        renamer = FileRenamer(folder_path)
    except ValueError as e:
        print(f"错误: {e}")
        return
    
    # 显示找到的文件数量
    all_files = renamer.get_all_files()
    print(f"找到 {len(all_files)} 个文件")
    
    while True:
        print("\n请选择操作:")
        print("1. 替换文件名中的文本")
        print("2. 删除文件名中的指定文本")
        print("3. 使用正则表达式重命名")
        print("4. 退出")
        
        choice = input("请输入选择 (1-4): ").strip()
        
        if choice == '4':
            break
        
        # 文件过滤器
        file_filter = input("文件过滤器 (如 *.txt，留空处理所有文件): ").strip()
        if not file_filter:
            file_filter = None
        
        if choice == '1':
            # 替换文本
            old_text = input("要替换的文本: ").strip()
            new_text = input("替换为: ").strip()
            case_sensitive = input("区分大小写? (y/n, 默认y): ").strip().lower() != 'n'
            
            # 预览
            print("\n=== 预览模式 ===")
            results = renamer.replace_text(old_text, new_text, case_sensitive, file_filter, dry_run=True)
            print_results(results)
            
            if results:
                confirm = input("\n确认执行? (y/n): ").strip().lower()
                if confirm == 'y':
                    print("\n=== 执行结果 ===")
                    results = renamer.replace_text(old_text, new_text, case_sensitive, file_filter, dry_run=False)
                    print_results(results)
        
        elif choice == '2':
            # 删除文本
            text_to_remove = input("要删除的文本: ").strip()
            case_sensitive = input("区分大小写? (y/n, 默认y): ").strip().lower() != 'n'
            
            # 预览
            print("\n=== 预览模式 ===")
            results = renamer.remove_text(text_to_remove, case_sensitive, file_filter, dry_run=True)
            print_results(results)
            
            if results:
                confirm = input("\n确认执行? (y/n): ").strip().lower()
                if confirm == 'y':
                    print("\n=== 执行结果 ===")
                    results = renamer.remove_text(text_to_remove, case_sensitive, file_filter, dry_run=False)
                    print_results(results)
        
        elif choice == '3':
            # 正则表达式重命名
            pattern = input("正则表达式模式: ").strip()
            replacement = input("替换字符串: ").strip()
            
            try:
                # 预览
                print("\n=== 预览模式 ===")
                results = renamer.rename_with_pattern(pattern, replacement, file_filter, dry_run=True)
                print_results(results)
                
                if results:
                    confirm = input("\n确认执行? (y/n): ").strip().lower()
                    if confirm == 'y':
                        print("\n=== 执行结果 ===")
                        results = renamer.rename_with_pattern(pattern, replacement, file_filter, dry_run=False)
                        print_results(results)
            except re.error as e:
                print(f"正则表达式错误: {e}")
        
        else:
            print("无效选择，请重新输入")


if __name__ == "__main__":
    main()